package com.dingtalk.h5app.quickstart.service;

import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiProcessinstanceGetRequest;
import com.dingtalk.api.request.OapiProcessinstanceListidsRequest;
import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
import com.dingtalk.api.response.OapiProcessinstanceListidsResponse;
import com.dingtalk.h5app.quickstart.config.UserDefineUrlConstant;
import com.dingtalk.h5app.quickstart.domain.WordInstance.InstanceBookMarkEntityVO;
import com.dingtalk.h5app.quickstart.domain.WordInstance.InstanceTableEntityVO;
import com.dingtalk.h5app.quickstart.domain.entity.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.taobao.api.ApiException;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
public class ParseEhnService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    /*@Autowired
    @Qualifier("com.dingtalk.h5app.quickstart.service.DingdingSerivceImpl")
    private JDYInterface dingdingimpl;*/

    @Autowired
    private DingdingSerivceImpl dingdingSerivce;
    public  void handleProcessModuleList(List<ProcessModuleVoEntity> processModuleVoEntities,String accessToken,Mapper dozerMapper ){
        //获取数据库中当前的所有表

        for(ProcessModuleVoEntity processModuleVoEntity:processModuleVoEntities){
            if(processModuleVoEntity.getProcessCode().equalsIgnoreCase("PROC-BD305341-CC47-4349-9A51-F4BD44860F51"))
                handleProcessModule(processModuleVoEntity,accessToken,dozerMapper);
            // 测试的时候，采用这一个process实例
            //针对每一个模板，要获取数据库的表名，分析是否在数据库中已经有主表。
            //如果有主表，根据id判断就更新。如果没有主表，那么就新增

        }
    }

    private  void handleProcessModule(ProcessModuleVoEntity processModuleVoEntity,String accessToken,Mapper dozerMapper ) {
        //第一次与api进行交互，获得所有的模板
        JSONObject jsonObject= getAllInstanceList(processModuleVoEntity.getProcessCode(),accessToken);
        List<String> InstanceList=(List<String>)jsonObject.get("instanceList");
        //处理所有的模板，判断在数据库中，是否有这个表。如果没有，那么就创建这个表，子表暂时不创建

            List<FormDIngding> formDIngdings= handleALLInstance(InstanceList,accessToken);
            //对所有的form进行处理，获取到全的id及最新的name；暂时未考虑表格
            FormDIngding formDIngding= getAllidAndLastName(formDIngdings);


            String lastInstance=(String)jsonObject.get("lastInstance");
           if(!isExistTableNameInDB("",processModuleVoEntity.getName())){
               //新建数据表，按照最新的字段的中文作为字段来进行建表
               //建关联的字表
               //需要先把json文件转为类文件，然后进行操作。转为Widget及cell
                //经过测试发现，如果钉钉中表单中字段被删除，仅仅影响后期的值，前期录入的值，不会变化

               //为简化起见，第一次，就根据最后一次记录，来创建表。
               getLastedInstanceFromDingding(lastInstance,accessToken);
               //  createTableBasedOnWidget() 后面继续实行

           }
               //插入数据

            for(String each :InstanceList){
                handleEachInstance(each,accessToken,dozerMapper);
            }
    }

    private FormDIngding getAllidAndLastName(List<FormDIngding> formDIngdings) {
        FormDIngding formDIngding=new FormDIngding();
        for(FormDIngding fd:formDIngdings) {
            for (Widget widget : fd.getWidgetList()) {
                Long count=formDIngding.getWidgetList()
                        .stream()
                        .filter(the -> the.getId().equalsIgnoreCase(widget.getId()))
                        .count();
                if(count==0){
                    formDIngding.getWidgetList().add(widget);
                    formDIngding.setCreatetime(fd.getCreatetime());
                }
                if(count>0){
                    //把时间大的覆盖掉时间小的
                    if(fd.getCreatetime().after(formDIngding.getCreatetime())){
                        Widget reswidget= formDIngding.getWidgetList()
                                .stream()
                                .filter(x->x.getId().equalsIgnoreCase(widget.getId()))
                                .findFirst()
                                .get();
                        reswidget.setValue(widget.getValue());
                    }


                }
            }
        }
        return formDIngding;
    }

    /*
    * 全部转换为FormDingDing的类，便于后面的处理
    * */
    private List<FormDIngding> handleALLInstance(List<String> instanceList,String accessToken) {
        List<FormDIngding> formDIngdings=new ArrayList<>();
        try {
            for(String instance:instanceList) {
                FormDIngding formDIngding=new FormDIngding();
                formDIngdings.add(formDIngding);
                DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/get");
                OapiProcessinstanceGetRequest req = new OapiProcessinstanceGetRequest();
                req.setProcessInstanceId(instance);
                OapiProcessinstanceGetResponse rsp = client.execute(req, accessToken);
                ResponseconvertToWiget(rsp,formDIngding);
                System.out.println(rsp.getBody());
            }
        }catch (Exception ex){

        }
        return formDIngdings;
    }

    private  void getLastedInstanceFromDingding(String lastInstance,String accessToken) {
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/get");
            OapiProcessinstanceGetRequest req = new OapiProcessinstanceGetRequest();
            req.setProcessInstanceId(lastInstance);
            OapiProcessinstanceGetResponse rsp = client.execute(req, accessToken);
            //ResponseconvertToWiget(rsp,fo);
            System.out.println(rsp.getBody());
        } catch (ApiException e) {
            e.printStackTrace();
        }

    }

    private void ResponseconvertToWiget(OapiProcessinstanceGetResponse rsp,FormDIngding formDIngding) {
        List<OapiProcessinstanceGetResponse.FormComponentValueVo> formComponentValueVos  =rsp.getProcessInstance().getFormComponentValues();
        for(OapiProcessinstanceGetResponse.FormComponentValueVo fvo:formComponentValueVos){
            Widget widget=new Widget();
            if(fvo.getComponentType().equalsIgnoreCase("TableField")){
                convertTable(fvo,widget);
            }
            if(fvo.getComponentType().equalsIgnoreCase("DDPhotoField")){
                convertPicture(fvo,widget);
            }
            if(fvo.getComponentType().equalsIgnoreCase("TextField")){
                convertText(fvo,widget);
            }
            formDIngding.getWidgetList().add(widget);
        }

        formDIngding.setCreatetime(rsp.getProcessInstance().getCreateTime());
    }

    private void convertTable(OapiProcessinstanceGetResponse.FormComponentValueVo fvo, Widget widget) {
        String jsonString=fvo.getValue();
        jsonString=jsonString.replace("\\","");
        ObjectMapper objectMapper=new ObjectMapper();
        try {
            JSONObject jsonObject1 =JSONObject.parseObject(jsonString);
            //Object xx=jsonObject1.get("rowValue");
            List<RowValue> rowValues = objectMapper.readValue(jsonString, new TypeReference<List<RowValue>>() {
            });
            handleTable(rowValues);
        }catch (Exception ex){
            System.out.println(ex.toString());
        }
    }

    private void convertPicture(OapiProcessinstanceGetResponse.FormComponentValueVo fvo, Widget widget) {
        widget.setId(fvo.getId());
        widget.setType(fvo.getComponentType());
        widget.setName(fvo.getValue());
        widget.setValue(fvo.getName());
    }

    private void convertText(OapiProcessinstanceGetResponse.FormComponentValueVo fvo,Widget widget) {
        widget.setId(fvo.getId());
        widget.setType(fvo.getComponentType());
        widget.setName(fvo.getValue());
        widget.setValue(fvo.getName());

    }
   /* private void createTableBasedProcessModel(String tablename){
        //同时创建主表及字表,
        String beginSql="CREATE TABLE `";
        String sqltablename=tablename;
        String mid="` (";
        String fieldStr=createFieldString(widgetList);
        String end=") ENGINE=InnoDB DEFAULT CHARSET=utf8;";

        String sql=beginSql+sqltablename+mid+fieldStr+end;
        jdbcTemplate.execute(sql);

    }*/
    private void createTableBasedOnWidget(List<Widget> widgetList, String tablename) {
        //同时创建主表及字表,
        String beginSql="CREATE TABLE `";
        String sqltablename=tablename;
        String mid="` (";
        String fieldStr=createFieldString(widgetList);
        String end=") ENGINE=InnoDB DEFAULT CHARSET=utf8;";

        String sql=beginSql+sqltablename+mid+fieldStr+end;
        jdbcTemplate.execute(sql);

        //创建子表，这个地方有点错误
        List<Widget> cellwidgetList=widgetList.stream()
                .filter(t->t.getType().equalsIgnoreCase("subform"))
                .collect(Collectors.toList());
        for(Widget widget:cellwidgetList){
            sqltablename=widget.getName();
            fieldStr=createsubtableFieldString(widget.getCellwidgetList());
            sql=beginSql+sqltablename+mid+fieldStr+end;
            jdbcTemplate.execute(sql);
        }

    }
    private String createsubtableFieldString(List<Cellwidget> cellwidgetList) {
        String fieldStr="";
        for(Cellwidget cellwidget:cellwidgetList){
            fieldStr+="`"+cellwidget.getName()+"` varchar(255) DEFAULT NULL,";
        }
        fieldStr+=fieldStr+"`fid` varchar(255) NOT NULL";
        // 删除最后一个,
        //fieldStr=fieldStr.substring(0,fieldStr.length()-1);
        return fieldStr;
    }
    private String createFieldString(List<Widget> widgetList) {
        String fieldStr="";
        fieldStr+=fieldStr+"`_id` varchar(255) NOT NULL ,";
        for(Widget widget:widgetList){
            fieldStr+="`"+widget.getName()+"` varchar(255) DEFAULT NULL,";
        }
        // 删除最后一个,
        fieldStr=fieldStr.substring(0,fieldStr.length()-1);
        return fieldStr;
    }

    public  boolean isExistTableNameInDB(String dataBase,String tablename){
        boolean isExist=false;
        String tablesql="SELECT table_name tableName, ENGINE, table_comment tableComment, create_time createTime ,TABLE_ROWS  FROM information_schema.TABLES WHERE  table_schema = ( SELECT DATABASE ( ) );";
        //获取一个表的所有列
        List<DataBaseTable> dataBaseTableList=new ArrayList<>();
        jdbcTemplate.query(tablesql,new RowCallbackHandler(){
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                // TODO Auto-generated method stub
                DataBaseTable dataBaseTable = new DataBaseTable();
                dataBaseTable.setEngine(rs.getString("ENGINE"));
                dataBaseTable.setTablecomment(rs.getString("tableComment"));
                dataBaseTable.setTablerows(rs.getInt("TABLE_ROWS"));
                dataBaseTable.setTalename(rs.getString("tableName"));
                /*cat.setId(rs.getInt("id"));
                cat.setMother_id(rs.getInt("mother_id"));
                cat.setDescription(rs.getString("description"));
                cat.setCreateDate(rs.getDate("creatDate"));*/
                //####do something
                dataBaseTableList.add(dataBaseTable);
            }
        });
        Long count=dataBaseTableList.stream().filter(t->t.getTalename().equalsIgnoreCase(tablename)).count();
        if(count>0){
            isExist=true;
        }
        return isExist;
    }


    private static JSONObject getAllInstanceList(String processCode,String accessToken) {
        JSONObject jsonObject=new JSONObject();
        List<String> instanceList=new ArrayList<>();
        try {
            DingTalkClient client = new DefaultDingTalkClient(UserDefineUrlConstant.URL_PROCESSINSTANCE_LISTIDS);
            OapiProcessinstanceListidsRequest req = new OapiProcessinstanceListidsRequest();
            //可以通过/process/listbyuserid，根据用户id获取可见审批模板列表.这个模板就是word的设计模板
            //req.setProcessCode("PROC-735AEDFB-4179-4E08-889E-87DA12685A95");
            req.setProcessCode(processCode);
            req.setStartTime(1584969417L);//增加一个L
            //req.setCursor(10L);
            OapiProcessinstanceListidsResponse rsp = client.execute(req, accessToken);//在这个地方增加accessToken
            instanceList.addAll(rsp.getResult().getList());
            while (rsp.getResult().getNextCursor()!=null){
                req.setProcessCode(processCode);
                req.setStartTime(1584969417L);//增加一个L
                //req.setCursor(20L);
                req.setCursor(rsp.getResult().getNextCursor());
                rsp = client.execute(req, accessToken);
                instanceList.addAll(rsp.getResult().getList());
            }
        } catch (Exception ex) {

        }
        instanceList.forEach(x->System.out.println(x));
        jsonObject.put("instanceList",instanceList);
        //获取最后一条记录
        String lastInstance=instanceList.get(instanceList.size()-1);
        jsonObject.put("lastInstance",lastInstance);
        return jsonObject;
    }



    private static void handleEachInstance(String each,String accessToken, Mapper dozerMapper ) {
        try {
            DingTalkClient client = new DefaultDingTalkClient(UserDefineUrlConstant.URL_PROCESSINSTANCE_GET);
            OapiProcessinstanceGetRequest req = new OapiProcessinstanceGetRequest();
            req.setProcessInstanceId(each);
            OapiProcessinstanceGetResponse rsp = client.execute(req, accessToken);

            parseInstance(rsp,dozerMapper);
            System.out.println(rsp.getBody());
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }
    public static void parseInstance(OapiProcessinstanceGetResponse rsp,Mapper dozerMapper) {
        OapiProcessinstanceGetResponse.ProcessInstanceTopVo processTopVo=rsp.getProcessInstance();
        ProcessInstanceEntity processInstanceEntity =dozerMapper.map(processTopVo,ProcessInstanceEntity.class);
        System.out.println("当前的instance:"+ processInstanceEntity.toString());

        List<OapiProcessinstanceGetResponse.FormComponentValueVo> formComponentValueVoEntities = processTopVo.getFormComponentValues();
        for(OapiProcessinstanceGetResponse.FormComponentValueVo formComponentValueVo:formComponentValueVoEntities){
            if(formComponentValueVo.getComponentType().equalsIgnoreCase("TableField")){
                handleTable(formComponentValueVo);
            }else {
                handleNotTable(formComponentValueVo);
            }
        }


    }

    private static void handleNotTable(OapiProcessinstanceGetResponse.FormComponentValueVo formComponentValueVo) {
        if(formComponentValueVo.getComponentType().equalsIgnoreCase("DDPhotoField")){
            String jsonString=formComponentValueVo.getValue();
            jsonString=jsonString.replace("\\","");
            jsonString=jsonString.substring(2,jsonString.length()-2);
            System.out.println("JSONSTring:"+jsonString);
            InstanceBookMarkEntityVO instanceBookMarkEntityVO=new InstanceBookMarkEntityVO();
            instanceBookMarkEntityVO.setId(UUID.randomUUID().toString());
            instanceBookMarkEntityVO.setBookmarkname(formComponentValueVo.getName());
            instanceBookMarkEntityVO.setBookmarkvalue(jsonString);
        }else {

        }
    }

    private static void handleTable(OapiProcessinstanceGetResponse.FormComponentValueVo formComponentValueVo) {

        String jsonString=formComponentValueVo.getValue();
        jsonString=jsonString.replace("\\","");
        ObjectMapper objectMapper=new ObjectMapper();
        try {
            JSONObject jsonObject1 =JSONObject.parseObject(jsonString);
            //Object xx=jsonObject1.get("rowValue");
            List<RowValue> rowValues = objectMapper.readValue(jsonString, new TypeReference<List<RowValue>>() {
            });
            handleTable(rowValues);
        }catch (Exception ex){
            System.out.println(ex.toString());
        }


    }

    private static void handleTable(List<RowValue> rowValues) {
        /*InstanceTableEntityVO instanceTableEntityVO=new InstanceTableEntityVO();
        instanceTableEntityVO.setId(UUID.randomUUID().toString());*/

        //继续写Code
    }
}


